package drds.binlog.prometheus;

import drds.binlog.instance.core.BinlogTask;
import drds.binlog.prometheus.impl.*;
import io.prometheus.client.Collector;
import io.prometheus.client.CollectorRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.List;

/**
 * @author Chuanyi Li
 */
public class InstanceExports
{

    public static final String DEST = "destination";
    public static final String[] DEST_LABELS = {DEST};
    public static final List<String> DEST_LABELS_LIST = Collections.singletonList(DEST);
    private static final Logger logger = LoggerFactory.getLogger(InstanceExports.class);
    private final Collector storeCollector;
    private final Collector entryCollector;
    private final Collector metaCollector;
    private final Collector sinkCollector;
    private final Collector parserCollector;

    private InstanceExports()
    {
        this.storeCollector = StoreCollector.instance();
        this.entryCollector = EntryCollector.instance();
        this.metaCollector = MetaCollector.instance();
        this.sinkCollector = SinkCollector.instance();
        this.parserCollector = ParserCollector.instance();
    }

    public static InstanceExports instance()
    {
        return SingletonHolder.SINGLETON;
    }

    public void initialize()
    {
        storeCollector.register();
        entryCollector.register();
        metaCollector.register();
        sinkCollector.register();
        parserCollector.register();
    }

    public void terminate()
    {
        CollectorRegistry.defaultRegistry.unregister(storeCollector);
        CollectorRegistry.defaultRegistry.unregister(entryCollector);
        CollectorRegistry.defaultRegistry.unregister(metaCollector);
        CollectorRegistry.defaultRegistry.unregister(sinkCollector);
        CollectorRegistry.defaultRegistry.unregister(parserCollector);
    }

    void register(BinlogTask binlogTask)
    {
        requiredInstanceRegistry(storeCollector).register(binlogTask);
        requiredInstanceRegistry(entryCollector).register(binlogTask);
        requiredInstanceRegistry(metaCollector).register(binlogTask);
        requiredInstanceRegistry(sinkCollector).register(binlogTask);
        requiredInstanceRegistry(parserCollector).register(binlogTask);
        logger.info("Successfully register metrics for binlogTask {}.", binlogTask.getDestination());
    }

    void unregister(BinlogTask binlogTask)
    {
        requiredInstanceRegistry(storeCollector).unregister(binlogTask);
        requiredInstanceRegistry(entryCollector).unregister(binlogTask);
        requiredInstanceRegistry(metaCollector).unregister(binlogTask);
        requiredInstanceRegistry(sinkCollector).unregister(binlogTask);
        requiredInstanceRegistry(parserCollector).unregister(binlogTask);
        logger.info("Successfully unregister metrics for binlogTask {}.", binlogTask.getDestination());
    }

    private InstanceRegistry requiredInstanceRegistry(Collector collector)
    {
        if (!(collector instanceof InstanceRegistry))
        {
            throw new IllegalArgumentException("BinlogTaskInfo prometheus collector need to implement InstanceRegistry.");
        }
        return (InstanceRegistry) collector;
    }

    private static class SingletonHolder
    {
        private static final InstanceExports SINGLETON = new InstanceExports();
    }

}
